package book.java.effective;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

/**
 * 如果我们希望一个类能被序列化，那么这个类直接实现Serializable就可以了,但是这样能否保证被反序列化过后还是单例呢？
 *
 * @author liubin
 *
 * @date 2018年3月2日上午9:46:07
 */
public class Instance implements Serializable {

    private static final long serialVersionUID = 177994265455689046L;

    private static final Instance obj = new Instance();

    private Instance() {}

    public static Instance getInstance() {
        return obj;
    }

    // 这就说明被反序列化过后便不再是单例。要保证单例还必须在单例类中实现readResolve的方法：
    // 于为什么要实现readResolve，这个方法并不是Serializable接口的方法，在此我并没有深究，究其原因估计是在反序列化的时候会调用这个奇怪的方法。
    private Object readResolve() {
        return obj;
    }

    @SuppressWarnings("resource")
    public static void main(String[] args) throws Exception {

        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("D:\\objFile.obj"));
        Instance instance = Instance.getInstance();
        out.writeObject(instance);
        out.close();

        ObjectInputStream in = new ObjectInputStream(new FileInputStream("D:\\objFile.obj"));
        Instance instance1 = (Instance) in.readObject();
        in = new ObjectInputStream(new FileInputStream("D:\\objFile.obj"));
        Instance instance2 = (Instance) in.readObject();

        // 比较两个实例对象的hash值，可以看到执行结果为：
        // obj1 hashcode:1915318863
        // obj2 hashcode:1283928880
        // 这就说明被反序列化过后便不再是单例。要保证单例还必须在单例类中实现readResolve的方法：

        System.out.println("obj1 hashcode:" + instance1.hashCode());
        System.out.println("obj2 hashcode:" + instance2.hashCode());

        in.close();

    }
}
